//package com.mall.search.server.service.impl;
//
//import com.alibaba.fastjson.JSON;
//import com.mall.search.common.domain.SkuEsModel;
//import com.mall.search.server.service.EsSearchService;
//import com.mall.search.server.vo.SearchParam;
//import com.mall.search.server.vo.SearchResult;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.lucene.search.join.ScoreMode;
//import org.elasticsearch.action.search.SearchRequest;
//import org.elasticsearch.action.search.SearchResponse;
//import org.elasticsearch.client.RequestOptions;
//import org.elasticsearch.client.RestHighLevelClient;
//import org.elasticsearch.index.query.BoolQueryBuilder;
//import org.elasticsearch.index.query.NestedQueryBuilder;
//import org.elasticsearch.index.query.QueryBuilders;
//import org.elasticsearch.index.query.RangeQueryBuilder;
//import org.elasticsearch.search.SearchHit;
//import org.elasticsearch.search.SearchHits;
//import org.elasticsearch.search.aggregations.AggregationBuilders;
//import org.elasticsearch.search.aggregations.Aggregations;
//import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
//import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
//import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
//import org.elasticsearch.search.aggregations.bucket.terms.Terms;
//import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
//import org.elasticsearch.search.builder.SearchSourceBuilder;
//import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
//import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
//import org.elasticsearch.search.sort.SortOrder;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//
//import java.io.IOException;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//
//@Service
//public class EsSearchServiceImpl implements EsSearchService {
//
//
//    @Autowired
//    private RestHighLevelClient client;
//
//    /**
//     * 查询es，根据查询条件searchParam,返回封装结果集result
//     *
//     * @param searchParam
//     * @return
//     */
//    @Override
//    public SearchResult search(SearchParam searchParam) throws IOException {
//
//        //1. 构建searchRequest
//        SearchRequest searchRequest = buildSearchRequest(searchParam);
//
//
//        //2. 执行search
//        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//
//
//        //3. 解析response
//        SearchResult searchResult = analyzerResponse(searchResponse, searchParam);
//        return searchResult;
//    }
//
//
//    private SearchResult analyzerResponse(SearchResponse searchResponse, SearchParam searchParam) {
//        SearchResult searchResult = new SearchResult();
//
//        /**
//         hits
//         */
//        SearchHits hits = searchResponse.getHits();
//
//        /** * 查询到的所有商品信息*/
////        private List<SkuEsModel> products;
//        List skuEsModelList = new ArrayList();
//        for (SearchHit hit : hits.getHits()) {
//
//            String skuEsModelString = hit.getSourceAsString();
//            SkuEsModel skuEsModel = JSON.parseObject(skuEsModelString, SkuEsModel.class);
//
//            // 处理高亮
//            if (StringUtils.isNotBlank(searchParam.getKeyword())) {
//                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
//                HighlightField skuTitleHighlightField = highlightFields.get("skuTitle");
//
//
//                skuEsModel.setSkuTitle(skuTitleHighlightField.getFragments()[0].toString());
//
//            }
//
//            skuEsModelList.add(skuEsModel);
//
//        }
//
//        searchResult.setProducts(skuEsModelList);
//        /*** 当前页码*/
////        private Integer pageNum;
//        searchResult.setPageNum(searchParam.getPageNum());
//        /** 总记录数*/
////        private Long total;
//        searchResult.setTotal(hits.getTotalHits().value);
//        /** * 总页码*/
////        private Integer totalPages;
//        searchResult.setTotalPages(
//                Long.valueOf(searchResult.getTotal() % 20 == 0 ? searchResult.getTotal() / 20 : (searchResult.getTotal() / 20 + 1)).intValue()
//        );
//
//        /**
//         * ======================================
//         *
//         * 以下是agg聚合结果解析
//         */
//        Aggregations aggregations = searchResponse.getAggregations();
//        /** 当前查询到的结果, 所有涉及到的品牌*/
////        private List<SearchResult.BrandVo> brands;
//        ParsedLongTerms brandIdAgg = aggregations.get("brandIdAgg");
//        List<? extends Terms.Bucket> buckets = brandIdAgg.getBuckets();
//        List<SearchResult.BrandVo> brandVos = new ArrayList<>();
//        for (Terms.Bucket bucket : buckets) {
//            SearchResult.BrandVo brandVo = new SearchResult.BrandVo();
//            brandVo.setBrandId(Long.valueOf(bucket.getKeyAsString()));
//
//            Terms brandNameAgg = bucket.getAggregations().get("brandNameAgg");
//            String brandName = brandNameAgg.getBuckets().get(0).getKeyAsString();
//            brandVo.setBrandName(brandName);
//
//            brandVos.add(brandVo);
//        }
//        searchResult.setBrands(brandVos);
//        /*** 当前查询到的结果, 所有涉及到的分类*/
////        private List<SearchResult.CatalogVo> catalogs;
//        List<SearchResult.CatalogVo> catalogs = new ArrayList<>();
//        ParsedLongTerms catalogIdAgg = aggregations.get("catalogIdAgg");
//
//        List<? extends Terms.Bucket> catalogBuckets = catalogIdAgg.getBuckets();
//
//        for (Terms.Bucket catalogBucket : catalogBuckets) {
//            SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo();
//            String catalogId = catalogBucket.getKeyAsString();
//            catalogVo.setCatalogId(Long.valueOf(catalogId));
//            Terms catalogNameAgg = catalogBucket.getAggregations().get("catalogNameAgg");
//            String catalogName = catalogNameAgg.getBuckets().get(0).getKeyAsString();
//            catalogVo.setCatalogName(catalogName);
//            catalogs.add(catalogVo);
//        }
//        searchResult.setCatalogs(catalogs);
//        /** * 当前查询的结果 所有涉及到所有属性*/
////        private List<SearchResult.AttrVo> attrs;
//        List<SearchResult.AttrVo> attrs = new ArrayList<>();
//        ParsedNested attrsAgg = aggregations.get("attrsAgg");
//        Terms attrIdAgg = attrsAgg.getAggregations().get("attrIdAgg");
//
//        for (Terms.Bucket bucket : attrIdAgg.getBuckets()) {
//            SearchResult.AttrVo attrVo = new SearchResult.AttrVo();
//            //attrId
//            String attrId = bucket.getKeyAsString();
//            attrVo.setAttrId(Long.valueOf(attrId));
//
//            Aggregations attrIdBucketAggregations = bucket.getAggregations();
//            //attrName
//            Terms attrNameAgg = attrIdBucketAggregations.get("attrNameAgg");
//            String attrName = attrNameAgg.getBuckets().get(0).getKeyAsString();
//            attrVo.setAttrName(attrName);
//            //attrValues  []
//            Terms attrValueAgg = attrIdBucketAggregations.get("attrValueAgg");
//            List<String> values = new ArrayList<>();
//            for (Terms.Bucket attrValueAggBucket : attrValueAgg.getBuckets()) {
//                values.add(attrValueAggBucket.getKeyAsString());
//            }
//            attrVo.setAttrValue(values);
//
//            attrs.add(attrVo);
//
//        }
//        searchResult.setAttrs(attrs);
//
//        return searchResult;
//    }
//
//    private SearchRequest buildSearchRequest(SearchParam searchParam) {
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//
//        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        /**
//         * query  begin
//         */
//        //1.1 keyword
//        if (StringUtils.isNotEmpty(searchParam.getKeyword()))
//            boolQueryBuilder.must(QueryBuilders.matchQuery("skuTitle", searchParam.getKeyword()));
//        //1.2 catalog
//
//        if (searchParam.getCatalog3Id() != null)
//            boolQueryBuilder.filter(QueryBuilders.termQuery("catalogId", searchParam.getCatalog3Id()));
//        //1.3 brandId
//
//        if (searchParam.getBrandId() != null && searchParam.getBrandId().size() > 0) {
//            boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId", searchParam.getBrandId()));
//        }
//        //1.4 skuPrice  10_20000
//        //  10_20000   10_20000
//        if (StringUtils.isNotBlank(searchParam.getSkuPrice())) {
//            RangeQueryBuilder skuPrice = QueryBuilders.rangeQuery("skuPrice");
//
//            String[] prices = searchParam.getSkuPrice().split("_");
//            if (prices.length == 2) {
//                skuPrice.lte(prices[1]);
//                skuPrice.gte(prices[0]);
//            } else if (searchParam.getSkuPrice().startsWith("_")) {
//                skuPrice.lte(prices[1]);
//            } else if (searchParam.getSkuPrice().endsWith("_")) {
//                skuPrice.gte(prices[0]);
//            }
//            boolQueryBuilder.filter(skuPrice);
//        }
//        //1.5  nested  attrs   1_3:3&2_4:8
//
//        if(searchParam.getAttrs()!=null && searchParam.getAttrs().size()>0){
//
//            for (String attrStr : searchParam.getAttrs()) {
//
//                String[] s = attrStr.split("_");
//                String attrId = s[0];
//
//                String[] sttrValues = s[1].split(":");
//
//                BoolQueryBuilder boolNestedQueryBuilder = QueryBuilders.boolQuery();
//                boolNestedQueryBuilder.must(QueryBuilders.termQuery("attrs.attrId",attrId));
//                boolNestedQueryBuilder.must(QueryBuilders.termQuery("attrs.attrValue",sttrValues));
//
//                NestedQueryBuilder attrs = QueryBuilders.nestedQuery("attrs", boolNestedQueryBuilder, ScoreMode.None);
//                boolQueryBuilder.filter(attrs);
//            }
//
//
//        }
//        sourceBuilder.query(boolQueryBuilder);
//
//        /**
//         * =============================================
//         * query  end
//         */
//
//
//        //1.4 sort  saleCount_desc
//
//        if (StringUtils.isNotBlank(searchParam.getSort())) {
//            String[] strings = searchParam.getSort().split("_");
//
//            sourceBuilder.sort(strings[0], "asc".equalsIgnoreCase(strings[1]) ? SortOrder.ASC : SortOrder.DESC);
//        }
//
//        //1.6 分页
//        sourceBuilder.from(0);
//        sourceBuilder.size(20);
//
//        //1.7 高亮
//        HighlightBuilder highlightBuilder = new HighlightBuilder();
//        highlightBuilder.field("skuTitle");
//        highlightBuilder.preTags("<span style='color:skyblue;font-size:18px'>");
//        highlightBuilder.postTags("</span>");
//
//        sourceBuilder.highlighter(highlightBuilder);
//
//        //1.8  aggs
//        TermsAggregationBuilder brandIdAgg = AggregationBuilders.terms("brandIdAgg").field("brandId");
//        TermsAggregationBuilder brandNameAgg = AggregationBuilders.terms("brandNameAgg").field("brandName");
//        brandIdAgg.subAggregation(brandNameAgg);
//
//        TermsAggregationBuilder catalogIdAgg = AggregationBuilders.terms("catalogIdAgg").field("catalogId");
//        TermsAggregationBuilder catalogNameAgg = AggregationBuilders.terms("catalogNameAgg").field("catalogName");
//        catalogIdAgg.subAggregation(catalogNameAgg);
//
//
//        NestedAggregationBuilder nested = AggregationBuilders.nested("attrsAgg", "attrs");
//        TermsAggregationBuilder attrIdAgg = AggregationBuilders.terms("attrIdAgg").field("attrs.attrId");
//        TermsAggregationBuilder attrNameAgg = AggregationBuilders.terms("attrNameAgg").field("attrs.attrName");
//        TermsAggregationBuilder attrValueAgg = AggregationBuilders.terms("attrValueAgg").field("attrs.attrValue");
//
//        nested.subAggregation(attrIdAgg);
//        attrIdAgg.subAggregation(attrNameAgg);
//        attrIdAgg.subAggregation(attrValueAgg);
//
//        sourceBuilder.aggregation(brandIdAgg);
//        sourceBuilder.aggregation(catalogIdAgg);
//        sourceBuilder.aggregation(nested);
//
//
//        SearchRequest searchRequest = new SearchRequest();
//        searchRequest.indices("product");
//        searchRequest.source(sourceBuilder);
//
//        return searchRequest;
//    }
//}
